﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using DevExpress.Xpf.Grid;
using Microsoft.Reporting.WinForms.Internal.Soap.ReportingServices2005.Execution;
using Microsoft.Windows.Controls.Ribbon;
using SSRSTestGenerator.Controllers;
using SSRSTestGenerator.Models;
using SSRSTestGenerator.Views;
using System.Drawing.Printing;
using System.Reflection;
using System.Windows.Media.Imaging;
using System.Text;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Management;



namespace SSRSTestGenerator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : RibbonWindow
    {
        #region Class Variables
        private bool IsRegistered = false;
        private string RegKey = string.Empty;
        private string[,] passwordSt = null;
        private bool isEdited = false;
        private SSRSTestGenerator.Models.ClassEnumerations.ApplicationStatus isNewObject;
        App MainApp { get; set; }
        private ObservableCollection<NotificationArgs> lstNotifications;
        public ObservableCollection<NotificationArgs> LstNotifications
        {
            get { return lstNotifications; }
            set { lstNotifications = value; }
        }       
        #endregion

        public MainWindow()
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp = ((App)Application.Current); // reference to logging
                this.MainApp.LogMessage("Info", "MainWindow entered");
                
                this.RegKey = @"Software\AsynchronousLtd\Protection";
                this.passwordSt = new string[,] // 5X10
                {
                    {"GFHY", "OPHY","GHSW","JNYH","CFFR","VS5H","CD3T","C67N","F34F","F8J5"},                    
                    {"HGFD","POLK","DFRE","NBGH","JYUO","GECS","DFWU","GQAS","VRYE","CAER"}, 
                    {"ASDW","HJUM","VGTR","VFDS","PCFT","GEIK","CWTH","GETD","ETDA","EFQS"},
                    {"DRFW", "HNKO","GHER","RERW","SWVU","E4N7","2C8U","3F5N","3CFD","F5UT"},
                    {"ASDF","QWER","MKOG","EDFR","CVBH","DRFW","HNKO","GHER","RERW","SWVU"}


                };
                                
                InitializeComponent();
                
                //this.DetermineIfApplicationRegistered();
                DataContext = this;
                this.LstNotifications = new ObservableCollection<NotificationArgs>();                
            }
            finally
            {
                this.MainApp.LogMessage("Info","MainWindow exited");
                Mouse.OverrideCursor = null;
            }
        }

        #region Delegated Event Methods
        private void LoadReport_SavedReportXml(object sender, Models.ReportXmlArgs arg)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                if (!String.IsNullOrEmpty(arg.ReportXml))
                {
                    this.ctrlBuildAssertions.IsEnabled = true;
                    this.ctrlBuildAssertions.BuildTreeTabSelected(arg.ReportXml, ((SSRSTestGenerator.Models.ClassProperties)(this.projectFilesView.FocusedNode.Content)).Name);

                    // set the test environment
                    if (chkBxNUnitTest.IsChecked == true) this.ctrlBuildAssertions.TestFramework = Models.ClassEnumerations.TestFrameworks.NUnit;
                    else this.ctrlBuildAssertions.TestFramework = Models.ClassEnumerations.TestFrameworks.VSTest;

                    // set development language
                    if (this.languageCSharp.IsChecked == true) this.ctrlBuildAssertions.Language = Models.ClassEnumerations.CodeLanguages.CSharp;
                    else this.ctrlBuildAssertions.Language = Models.ClassEnumerations.CodeLanguages.VB;

                    // get project name from project tree
                    TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                    nodeIterator.MoveNext();
                    this.UpdateBuildAssertionControl(nodeIterator.Current.Content.ToString(), arg.ReportParameters);

                    this.tabControls.SelectedTabIndex = 1;

                    // update existing tag object as user may have updated the class properties
                    TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                    if (selectedNode.Tag is ClassProperties)
                    {
                        ClassProperties prop = (ClassProperties)selectedNode.Tag;
                        prop.ReportParameters = arg.ReportParameters; // update parameter array      
                        prop.Xml = arg.ReportXml;
                        selectedNode.Tag = prop; // reassign object to tree node

                        // update root node's class collection
                        ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;
                        // update class collection in root - find and replace updated class in root node collection of classes                    
                        for (int outerLoop = 0; outerLoop <= props.ClassProperties.Count; outerLoop++)
                        {
                            if (props.ClassProperties[outerLoop].Name == ((ClassProperties)selectedNode.Tag).Name)
                            {
                                props.ClassProperties[outerLoop].Xml = arg.ReportXml;
                                nodeIterator.Current.Tag = props; // update existing project node
                                break;
                            }
                        }
                    }
                }
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void ctrlBuildAssertions_CreatedTests(object sender, Models.TestCodeArgs arg)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                if (!String.IsNullOrEmpty(arg.ReportCode))
                {
                    this.ctrlGenerateTestCode.IsEnabled = true;

                    // set the test environment
                    if (this.chkBxNUnitTest.IsChecked == true) this.ctrlGenerateTestCode.TestFramework = Models.ClassEnumerations.TestFrameworks.VSTest;
                    else this.ctrlGenerateTestCode.TestFramework = Models.ClassEnumerations.TestFrameworks.NUnit;

                    // set development language
                    if (this.languageCSharp.IsChecked == true) this.ctrlGenerateTestCode.Language = Models.ClassEnumerations.CodeLanguages.CSharp;
                    else this.ctrlGenerateTestCode.Language = Models.ClassEnumerations.CodeLanguages.VB;

                    // set the code
                    this.ctrlGenerateTestCode.BindCodeToEditorBuildTreeTabSelected(arg.ReportCode);

                    //selected the 3rd tab
                    this.tabControls.SelectedTabIndex = 2;

                    // update root node's class collection      
                    TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                    if (selectedNode.Tag is ClassProperties)
                    {
                        // update selected node
                        ((ClassProperties)selectedNode.Tag).Code = arg.ReportCode;

                        // get the root node and update it's collection of classes
                        TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                        nodeIterator.MoveNext();
                        ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;
                        // update class collection in root - find and replace updated class in root node collection of classes                    
                        for (int outerLoop = 0; outerLoop <= props.ClassProperties.Count; outerLoop++)
                        {
                            if (props.ClassProperties[outerLoop].Name == ((ClassProperties)selectedNode.Tag).Name)
                            {
                                props.ClassProperties[outerLoop].Code = arg.ReportCode;
                                nodeIterator.Current.Tag = props; // update existing project node
                                break;
                            }
                        }
                    }
                }
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void UpdatePropertiesClassTestCount(object sender, Models.TestCodeArgs arg)
        {
            //update over all text counter based on this change
        }
        private void UpdateStatusProgressBars(object sender, Models.StatusProgressBarArgs arg)
        {
            // this.mainPrgBar.Value = arg.ProgressBarValue;
        }
        private void UpdateNotifications(object sender, Models.NotificationArgs arg)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;

                this.LstNotifications.Insert(0, arg);
                this.lstBoxNotifications.ItemsSource = this.LstNotifications;
                this.lstBoxNotifications.SelectedIndex = 0;
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void UpdateProjectProperties(object sender, PropsArg arg)
        {
            //ProjectProperties props = arg.ProjectProps;
        }
        private void newProjectChildWindow_NewPrjPropEvent(object sender, PropsArg arg)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;

                // cast args to be class or project object
                if (arg.AppTypeObject == ClassEnumerations.ApplicationType.Class)
                {
                    this.EditedProject(); // project has been dirtied

                    if (isNewObject == ClassEnumerations.ApplicationStatus.New)
                    {
                        // get root node property
                        TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                        nodeIterator.MoveNext();
                        this.CreateChildNode(nodeIterator.Current, (ClassProperties)arg.Properties, true); // set focus on this created class

                        // default
                        this.classTestCount.Text = "0";
                        this.lstBxReportParameters.Items.Clear();

                        // add class to project props collection of classes
                        ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;
                        if (props.ClassProperties == null) props.ClassProperties = new List<ClassProperties>();
                        props.ClassProperties.Add((ClassProperties)arg.Properties);

                    }
                    else //update
                    {
                        // child node   
                        TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                        selectedNode.Tag = arg.Properties;
                        ((SSRSTestGenerator.Models.ClassProperties)(this.projectFilesView.FocusedNode.Content)).Name = ((ClassProperties)arg.Properties).Name;

                        // root node
                        TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                        nodeIterator.MoveNext();
                        ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;

                        // update class collection in root - find and replace updated class in root node collection of classes                    
                        for (int outerLoop = 0; outerLoop <= props.ClassProperties.Count; outerLoop++)
                        {
                            if (props.ClassProperties[outerLoop].Name == ((ClassProperties)selectedNode.Tag).Name)
                            {
                                props.ClassProperties[outerLoop] = (ClassProperties)arg.Properties;
                                nodeIterator.Current.Tag = props; // update existing project node                                                       

                                //nodeIterator.Current.Content = ((ClassProperties)arg.Properties).Name;
                                // TODO: rebuil tree after a change
                                break;
                            }
                        }

                        // update build assert ctrl with new class name
                        if (((ClassProperties)arg.Properties).TreeNodeAssertionDetails != null)
                        {
                            foreach (NodeDetails details in ((ClassProperties)arg.Properties).TreeNodeAssertionDetails)
                            {
                                for (int loop = 0; loop < this.ctrlBuildAssertions.LstNodeDetails.Count; loop++)
                                {
                                    if (details.NodeID == this.ctrlBuildAssertions.LstNodeDetails[loop].NodeID)
                                    {
                                        this.ctrlBuildAssertions.LstNodeDetails[loop] = details;
                                    }
                                }
                            }
                        }

                        // determine what should happen to the xml and code controls
                        if (((ClassProperties)arg.Properties).Xml == String.Empty)
                        {
                            this.ctrlBuildAssertions.trViewReportXml.Items.Clear();
                        }
                        if (((ClassProperties)arg.Properties).Code == String.Empty)
                        {
                            this.ctrlGenerateTestCode.txtCode.Text = String.Empty;
                        }

                    }

                    this.txtBlkReportname.Text = ((ClassProperties)arg.Properties).ReportName;
                    this.txtBlkReportPath.Text = ((ClassProperties)arg.Properties).ReportFolder;
                    this.credentialsUsername.Text = ((ClassProperties)arg.Properties).Credentials == null ? String.Empty : ((ClassProperties)arg.Properties).Credentials.Username;
                    this.credentialsPassword.Text = ((ClassProperties)arg.Properties).Credentials == null ? String.Empty : ((ClassProperties)arg.Properties).Credentials.Password;
                    this.credentialsDomain.Text = ((ClassProperties)arg.Properties).Credentials == null ? String.Empty : ((ClassProperties)arg.Properties).Credentials.Domian;

                    // this.ctrlBuildAssertions.IsEnabled = true;
                }
                else if (arg.AppTypeObject == ClassEnumerations.ApplicationType.Project)
                {
                    if (isNewObject == ClassEnumerations.ApplicationStatus.New)
                    {
                        this.isEdited = false; // new project - all clean

                        projectFilesView.Nodes.Clear(); // new project
                        TreeListNode rootNode = CreateRootNode((ProjectProperties)arg.Properties);

                        this.txtblkCreated.Text = ((ProjectProperties)arg.Properties).ProjectCraeted.ToString();
                        this.NumberOfTests.Text = "0";

                        // clear any existing class properties pnel
                        this.txtBlkReportname.Text = string.Empty;
                        this.txtBlkReportPath.Text = string.Empty;
                        this.credentialsUsername.Text = string.Empty;
                        this.credentialsPassword.Text = string.Empty;
                        this.credentialsDomain.Text = string.Empty;
                        this.classTestCount.Text = string.Empty;
                        this.lstBxReportParameters.Items.Clear();

                        this.ctrlGenerateTestCode.IsEnabled = this.ctrlBuildAssertions.IsEnabled = false;
                        this.btnEditProperties.IsEnabled = this.btnNewClass.IsEnabled = this.btnSave.IsEnabled = true;
                        this.btnReportGerParams.IsEnabled = this.btnReportCallReport.IsEnabled = false;

                        this.imgLoadreport.Visibility = System.Windows.Visibility.Collapsed;
                        this.DemoDockContainer.Visibility = System.Windows.Visibility.Visible;
                        this.ctrlLoadReport.Visibility = System.Windows.Visibility.Visible;

                        // notify user
                        this.UpdateNotifications(this, new NotificationArgs() { Message = "New project '" + ((ProjectProperties)arg.Properties).Name + "' created", ImagePath = "/Images/16x16-Valid.png" });
                    }
                    else // update
                    {
                        this.EditedProject(); // project has been dirtied

                        // get root node properties
                        TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                        nodeIterator.MoveNext();
                        nodeIterator.Current.Tag = arg.Properties;

                        // get the number of test from each class test (count assertions) - put sum in props panel
                        int totalAssertions = 0;
                        foreach (ClassProperties clsProps in ((ProjectProperties)arg.Properties).ClassProperties)
                        {
                            totalAssertions += clsProps.NumberOfClassTests;
                        }
                        this.NumberOfTests.Text = totalAssertions.ToString();                        
                    }

                    // update properties panel
                    this.serviceUrl.Text = ((ProjectProperties)arg.Properties).ReportWebServiceUrl;
                    this.reportServerUrl.Text = ((ProjectProperties)arg.Properties).ReportServerUrl;
                    this.txtblkSavedPath.Text = ((ProjectProperties)arg.Properties).ProjectSavedPath;

                    chkBxVSTest.IsChecked = ((ProjectProperties)arg.Properties).TestFramework == ClassEnumerations.TestFrameworks.VSTest ? true : false;
                    chkBxNUnitTest.IsChecked = ((ProjectProperties)arg.Properties).TestFramework == ClassEnumerations.TestFrameworks.NUnit ? true : false;
                    languageCSharp.IsChecked = ((ProjectProperties)arg.Properties).Language == ClassEnumerations.CodeLanguages.CSharp ? true : false;
                    languageVB.IsChecked = ((ProjectProperties)arg.Properties).Language == ClassEnumerations.CodeLanguages.VB ? true : false;

                    // update controls
                    this.ctrlLoadReport.ReportServiceUrl = this.serviceUrl.Text;
                }
            }
            catch (Exception ex)
            {
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Failed to create project '" + ((ProjectProperties)arg.Properties).Name + "' - " + ex.Message, ImagePath = "/Images/16x16-Errors.png" });
                throw (ex);
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void EditedProject()
        {
            this.btnSave.IsEnabled = true;
            this.isEdited = true;
        }
        private void ctrlBuildAssertions_UpdatedClassPropsWithNodeDetails(object sender, NodeDetails arg)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                bool isFound = false;

                // get root node property
                TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                nodeIterator.MoveNext();
                ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;

                //get the selected node (child) in tree' name - use that to filter out the class in properties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;

                for (int outerLoop = 0; outerLoop < props.ClassProperties.Count; outerLoop++)
                {
                    if (isFound) break; // found node in inner loop

                    if (props.ClassProperties[outerLoop].Name == ((ClassProperties)selectedNode.Tag).Name)
                    {
                        if (props.ClassProperties[outerLoop].TreeNodeAssertionDetails == null)
                        {
                            props.ClassProperties[outerLoop].TreeNodeAssertionDetails = new List<NodeDetails>();
                            isFound = true;
                            props.ClassProperties[outerLoop].TreeNodeAssertionDetails.Add(arg);
                        }
                        else
                        {
                            for (int innerLoop = 0; innerLoop < props.ClassProperties[outerLoop].TreeNodeAssertionDetails.Count; innerLoop++)
                            {
                                if (props.ClassProperties[outerLoop].TreeNodeAssertionDetails[innerLoop].NodeID == arg.NodeID)
                                {
                                    isFound = true;
                                    props.ClassProperties[outerLoop].TreeNodeAssertionDetails[innerLoop] = arg;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (!isFound) // NodeDetails is new
                {
                    for (int outerLoop = 0; outerLoop <= props.ClassProperties.Count; outerLoop++)
                    {
                        if (props.ClassProperties[outerLoop].Name == ((ClassProperties)selectedNode.Tag).Name)
                        {
                            props.ClassProperties[outerLoop].TreeNodeAssertionDetails.Add(arg);
                            break;
                        }
                    }
                }

                nodeIterator.Current.Tag = props; // reassign updated node to root tag          
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void UpdateRibbonBar(object sender, List<RibbonMenuItemArgs> ribItem)
        {
            try
            {
                foreach (RibbonMenuItemArgs item in ribItem)
                {
                    RibbonButton menuItem = (RibbonButton)this.FindName(item.RibbonButtonName);
                    menuItem.IsEnabled = item.IsRibbonButtonEnabled;
                }
            }
            catch (Exception ex) { throw ex; }
            finally { Mouse.OverrideCursor = null; }
        }
        private void ctrlBuildAssertions_AssertionActioned(object sender, bool addToCounter)
        {
            TreeListNode selectedNode = this.projectFilesView.FocusedNode;
            if (addToCounter)
            {
                ((ClassProperties)selectedNode.Tag).NumberOfClassTests++;
                this.classTestCount.Text = (int.Parse(this.classTestCount.Text) + 1).ToString();
                this.NumberOfTests.Text = (int.Parse(this.NumberOfTests.Text) + 1).ToString();

                this.UpdateNotifications(this, new NotificationArgs() { Message = "Assertion added successfully", ImagePath = "/Images/16x16-Valid.png" });
            }
            else
            {
                if (int.Parse(this.NumberOfTests.Text) == 0) return; // nothing to subtract from

                ((ClassProperties)selectedNode.Tag).NumberOfClassTests--;
                this.NumberOfTests.Text = (int.Parse(this.NumberOfTests.Text) - 1).ToString();
                this.classTestCount.Text = (int.Parse(this.classTestCount.Text) - 1).ToString();

                this.UpdateNotifications(this, new NotificationArgs() { Message = "Assertion removed successfully", ImagePath = "/Images/16x16-Valid.png" });
            }

            // is user able to generate code (you have to have assertions)
            this.btnReportCreateTests.IsEnabled = this.classTestCount.Text != "0" ? true : false;

            this.EditedProject(); // project has been updated
        }
        #endregion

        #region TreeControl Methods
        private TreeListNode CreateRootNode(object dataObject)
        {
            try
            {
                // Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","CreateRootNode entered");

                TreeListNode rootNode = new TreeListNode(dataObject);

                // load icon for root node
                BitmapImage logo = new BitmapImage();
                logo.BeginInit();
                logo.UriSource = new Uri("pack://application:,,,/SSRSTestGenerator;component/Images/16x16NewProjectpng.png");
                logo.EndInit();
              
                rootNode.Image = logo;
                rootNode.Tag = dataObject;
                projectFilesView.Nodes.Add(rootNode);

                this.projectFilesView.FocusedNode = rootNode;
                this.projectFilesView.Focus();

                return rootNode;
            }
            finally
            {
                this.MainApp.LogMessage("Info","CreateRootNode exited");
                // Mouse.OverrideCursor = null;
            }
        }
        private void CreateChildNode(TreeListNode parentNode, object dataObject, bool setFocus = false)
        {
            try
            {
                // Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","CreateChildNode entered");

                TreeListNode childNode = new TreeListNode(dataObject);

                // load icon for child node
                BitmapImage logo = new BitmapImage();
                logo.BeginInit();
                logo.UriSource = new Uri("pack://application:,,,/SSRSTestGenerator;component/Images/16x16NewClass.png");
                logo.EndInit();
                childNode.Image = logo;

                childNode.Tag = dataObject;
                parentNode.Nodes.Add(childNode);
                parentNode.ExpandAll();

                if (setFocus)
                {
                    this.projectFilesView.FocusedNode = childNode;
                    this.projectFilesView.Focus();
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","CreateChildNode exited");
                // Mouse.OverrideCursor = null;
            }
        }
        private void projectFilesView_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","projectFilesView_FocusedRowChanged entered");

                if (e.NewRow is ClassProperties && e.OldRow != null)
                {
                    // update the class properties panel
                    ClassProperties prop = (ClassProperties)e.NewRow;
                    TestClassSelectedInTreeView(prop);

                    // update the loadreport parameters
                    this.UpdateLoadReportControl();

                    // update the buildsassertions with xml and already assertions created
                    TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                    nodeIterator.MoveNext();

                    this.UpdateBuildAssertionControl(nodeIterator.Current.Content.ToString(), prop.ReportParameters);
                    this.ctrlBuildAssertions.ReportPath = prop.ReportFolder;
                    this.ctrlBuildAssertions.BuildTreeTabSelected(prop.Xml, ((SSRSTestGenerator.Models.ClassProperties)(this.projectFilesView.FocusedNode.Content)).Name); // build xml tree                                       
                    this.classTestCount.Text = prop.NumberOfClassTests.ToString();

                    // GenerateTestCode control
                    this.ctrlGenerateTestCode.ReportName = prop.ReportName;
                    this.ctrlGenerateTestCode.BindCodeToEditorBuildTreeTabSelected(prop.Code);                    
                    if (prop.Code != String.Empty) this.ctrlGenerateTestCode.IsEnabled = true;
                    else this.ctrlGenerateTestCode.txtCode.Text = String.Empty;

                    // enable controls
                    if (prop.Xml != String.Empty) this.btnClassEditProperties.IsEnabled = true;
                    else this.ctrlBuildAssertions.trViewReportXml.Items.Clear();

                    // clear the previous contents
                    this.ctrlBuildAssertions.lstBoxAssertions.Items.Clear();

                    // ribbonbar menut items                    
                    this.btnReportCreateTests.IsEnabled = prop.TreeNodeAssertionDetails.Count > 0 ? true : false;
                    this.btnCutPasteCode.IsEnabled = this.btnPrintCode.IsEnabled = String.IsNullOrEmpty(prop.Code) ? false : true;
                    this.btnClassDelete.IsEnabled = true;   // enable ribbon menu 
                    this.ctrlBuildAssertions.IsEnabled = true;
                    this.tabControls.SelectedTabIndex = 0; // report details
                    this.btnReportGerParams.IsEnabled = this.btnReportCallReport.IsEnabled = true;


                    if (!this.IsRegistered) this.TrialMode(); // trial mode
                }
                else
                {
                    this.btnReportGerParams.IsEnabled = this.btnReportCallReport.IsEnabled = this.btnCutPasteCode.IsEnabled = this.btnPrintCode.IsEnabled = this.btnClassDelete.IsEnabled = this.btnReportCreateTests.IsEnabled = this.btnClassEditProperties.IsEnabled = false;
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","projectFilesView_FocusedRowChanged exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void TestClassSelectedInTreeView(ClassProperties testClass)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","TestClassSelectedInTreeView entered");

                this.credentialsUsername.Text = testClass.Credentials == null ? string.Empty : testClass.Credentials.Username;
                this.credentialsPassword.Text = testClass.Credentials == null ? string.Empty : testClass.Credentials.Password;
                this.classTestCount.Text = testClass.NumberOfClassTests.ToString();
                this.txtBlkReportPath.Text = testClass.ReportFolder;
                this.txtBlkReportname.Text = testClass.ReportName;

                // loop around and get each class's report   
                if (testClass.ReportParameters != null)
                {
                    this.lstBxReportParameters.Items.Clear();
                    foreach (ParameterValue param in testClass.ReportParameters)
                    {
                        this.lstBxReportParameters.Items.Add(param.Name + " : " + param.Value);
                    }
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","TestClassSelectedInTreeView exited");
                Mouse.OverrideCursor = null;
            }
        }
        #endregion

        #region Control Events
        private void txtBlkReportPath_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                // update existing tag object as user may have updated the class properties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                ClassProperties prop = (ClassProperties)selectedNode.Tag;

                if (String.IsNullOrEmpty(((System.Windows.Controls.TextBox)(e.Source)).Text))
                {
                    MessageBox.Show("By leaving the report path empty, you are stating that this report is located on the root level of the reporting server.", "Report Path Missing", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                prop.ReportFolder = ((System.Windows.Controls.TextBox)(e.Source)).Text; // update report path (empty or not)
                selectedNode.Tag = prop; // reassign object to tree node
            }
            finally { Mouse.OverrideCursor = null; }

        }
        private void credentialsUsername_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                // update existing tag object as user may have updated the class properties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                ClassProperties prop = (ClassProperties)selectedNode.Tag;
                prop.Credentials.Username = ((System.Windows.Controls.TextBox)(e.Source)).Text.Trim();
                selectedNode.Tag = prop; // reassign object to tree node
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void credentialsPassword_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                // update existing tag object as user may have updated the class properties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                ClassProperties prop = (ClassProperties)selectedNode.Tag;

                // perform updates                           
                prop.Credentials.Password = ((System.Windows.Controls.TextBox)(e.Source)).Text.Trim();
                selectedNode.Tag = prop; // reassign object to tree node
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void txtBlkReportname_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                if (String.IsNullOrEmpty(((System.Windows.Controls.TextBox)(e.Source)).Text))
                {
                    MessageBox.Show("The report name cannot be empty, please enter the report that you wish to create a test class against.", "Report Name Missing", MessageBoxButton.OK, MessageBoxImage.Error);
                    txtBlkReportname.Focus();
                }
                else
                {
                    // update existing tag object as user may have updated the class properties
                    TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                    ClassProperties prop = (ClassProperties)selectedNode.Tag;

                    prop.ReportName = ((System.Windows.Controls.TextBox)(e.Source)).Text;
                    selectedNode.Tag = prop; // reassign object to tree node
                }
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void serviceUrl_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                ValidateWebSerivce validate = new ValidateWebSerivce();
                string errorMessage = string.Empty;
                if (!validate.ServiceExists(this.serviceUrl.Text, false, out errorMessage))
                {
                    MessageBox.Show(errorMessage);
                }
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void credentialsDomain_LostFocus(object sender, RoutedEventArgs e)
        {

            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                // update existing tag object as user may have updated the class properties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                ClassProperties prop = (ClassProperties)selectedNode.Tag;

                // perform updates                           
                prop.Credentials.Domian = ((System.Windows.Controls.TextBox)(e.Source)).Text.Trim();
                selectedNode.Tag = prop; // reassign object to tree node
            }
            finally { Mouse.OverrideCursor = null; }

        }
        private void reportServerUrl_LostFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                ValidateWebSerivce validate = new ValidateWebSerivce();
                string errorMessage = string.Empty;
                if (!validate.ServiceExists(this.reportServerUrl.Text, false, out errorMessage))
                {
                    MessageBox.Show(errorMessage);
                    this.lstBoxNotifications.Items.Add(new System.Windows.Controls.ListBoxItem() { Content = errorMessage });
                }
                else
                {
                    this.lstBoxNotifications.Items.Add(new System.Windows.Controls.ListBoxItem() { Content = "Report server url is valid." });
                }
            }
            finally { Mouse.OverrideCursor = null; }
        }
        private void RibbonWindow_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","RibbonWindow_Loaded entered");

                // populate project properties panel            
                if (projectFilesView.Nodes.Count > 0)
                {
                    TreeListNode rootNode = projectFilesView.Nodes[0];
                    ProjectProperties prop = (ProjectProperties)rootNode.Tag;
                    this.serviceUrl.Text = prop.ReportWebServiceUrl;                    
                    this.NumberOfTests.Text = prop.TotalProjectTests.ToString();
                    this.txtblkSavedPath.Text = prop.ProjectSavedPath;
                    this.txtblkCreated.Text = prop.ProjectCraeted.ToString();
                    this.reportServerUrl.Text = prop.ReportServerUrl;

                    chkBxVSTest.IsChecked = prop.TestFramework == ClassEnumerations.TestFrameworks.VSTest ? true : false;
                    chkBxNUnitTest.IsChecked = prop.TestFramework == ClassEnumerations.TestFrameworks.NUnit ? true : false;
                    languageCSharp.IsChecked = prop.Language == ClassEnumerations.CodeLanguages.CSharp ? true : false;
                    languageVB.IsChecked = prop.Language == ClassEnumerations.CodeLanguages.VB ? true : false;

                    this.UpdateNotifications(this, new NotificationArgs() { Message = "Reporting Service Test Generator - Application loaded", ImagePath = "/Images/16x16-Valid.png" });
                }
            }
            finally
            {
                this.DetermineIfApplicationRegistered();
                this.MainApp.LogMessage("Info","RibbonWindow_Loaded exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void tabControls_SelectedItemChanged(object sender, DevExpress.Xpf.Docking.Base.SelectedItemChangedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","tabControls_SelectedItemChanged entered");

                ClassProperties clsProps = null;
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                if (selectedNode != null)
                {
                    if (selectedNode.Tag is ClassProperties)
                    {
                        clsProps = (ClassProperties)selectedNode.Tag;
                    }
                }

                switch (e.Item.Tag.ToString())
                {
                    case "ReportDetails":
                        this.ctrlLoadReport.DetermineRibbonBarMenuItemsStatus();
                        if (this.classTestCount != null) this.btnReportCreateTests.IsEnabled = this.classTestCount.Text != "0" ? true : false;
                        break;
                    case "BuildAssertions":
                        this.ctrlBuildAssertions.DetermineRibbonBarMenuItemsStatus();
                        if (this.classTestCount != null) this.btnReportCreateTests.IsEnabled = this.classTestCount.Text != "0" ? true : false;
                        break;
                    case "UnitTestCode":
                        this.ctrlGenerateTestCode.DetermineRibbonBarMenuItemsStatus();
                        break;
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","tabControls_SelectedItemChanged exited");
            }
        }
        #endregion

        #region RibbonBar Events
        private void btnNewProject_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnNewProject_Click entered");

                if (this.isEdited)
                {
                    if (MessageBox.Show("You have unsaved changes within the current project, if you continue, all changes will be lost. Do you wish to continue?", "Unsaved Changes", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.No) return;
                }

                PropertiesWindow newProjectChildWindow = new PropertiesWindow(SSRSTestGenerator.Models.ClassEnumerations.ApplicationType.Project, null, ClassEnumerations.ApplicationStatus.New);
                newProjectChildWindow.NewPrjPropEvent += new PropertiesWindow.NewPrjProp(newProjectChildWindow_NewPrjPropEvent);
                newProjectChildWindow.NotifyedUser += new PropertiesWindow.NotifyUser(newProjectChildWindow_NotifyedUser);
                newProjectChildWindow.Owner = this;
                newProjectChildWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                
                newProjectChildWindow.ShowDialog();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnNewProject_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnNewClass_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnNewClass_Click entered");

                isNewObject = ClassEnumerations.ApplicationStatus.New;
                PropertiesWindow newProjectChildWindow = new PropertiesWindow(SSRSTestGenerator.Models.ClassEnumerations.ApplicationType.Class, null, ClassEnumerations.ApplicationStatus.New);
                newProjectChildWindow.NewPrjPropEvent += new PropertiesWindow.NewPrjProp(newProjectChildWindow_NewPrjPropEvent);
                newProjectChildWindow.CheckedDoesClassNameExist += new PropertiesWindow.CheckDoesClassNameExist(newProjectChildWindow_CheckedDoesClassNameExist);
                newProjectChildWindow.Owner = this;
                newProjectChildWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                
                newProjectChildWindow.ShowDialog();
                this.btnSave.IsEnabled = true;
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnNewClass_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnClassEditProperties_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnClassEditProperties_Click entered");

                // child node   
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                PropsArg arg = new PropsArg() { AppTypeObject = ClassEnumerations.ApplicationType.Class, IsUpdated = false, Properties = selectedNode.Tag, };
                this.isNewObject = ClassEnumerations.ApplicationStatus.Update; // current action is an update

                PropertiesWindow newProjectChildWindow = new PropertiesWindow(SSRSTestGenerator.Models.ClassEnumerations.ApplicationType.Class, arg, ClassEnumerations.ApplicationStatus.Update);
                newProjectChildWindow.NewPrjPropEvent += new PropertiesWindow.NewPrjProp(newProjectChildWindow_NewPrjPropEvent);
                newProjectChildWindow.CheckedDoesClassNameExist += new PropertiesWindow.CheckDoesClassNameExist(newProjectChildWindow_CheckedDoesClassNameExist);
                newProjectChildWindow.Owner = this;
                newProjectChildWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                
                newProjectChildWindow.ShowDialog();

                this.btnSave.IsEnabled = true;
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnClassEditProperties_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnEditProperties_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnEditProperties_Click entered");

                this.isNewObject = ClassEnumerations.ApplicationStatus.Update; // current action is an update

                TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                nodeIterator.MoveNext();
                PropsArg arg = new PropsArg() { AppTypeObject = ClassEnumerations.ApplicationType.Project, IsUpdated = false, Properties = nodeIterator.Current.Tag, };

                PropertiesWindow newProjectChildWindow = new PropertiesWindow(SSRSTestGenerator.Models.ClassEnumerations.ApplicationType.Project, arg, ClassEnumerations.ApplicationStatus.Update);

                newProjectChildWindow.NewPrjPropEvent += new PropertiesWindow.NewPrjProp(newProjectChildWindow_NewPrjPropEvent);
                newProjectChildWindow.NotifyedUser += new PropertiesWindow.NotifyUser(newProjectChildWindow_NotifyedUser);
                newProjectChildWindow.Owner = this;
                newProjectChildWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                
                newProjectChildWindow.ShowDialog();

                this.btnSave.IsEnabled = true;
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnEditProperties_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnSave_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnSave_Click entered");

                // get code if any and assign to current node
                string code = this.ctrlGenerateTestCode.txtCode.Text;
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                if (selectedNode.Tag is ClassProperties)
                {
                    ((ClassProperties)selectedNode.Tag).Code = code;
                }

                ReadXmlEntities xmlController = new ReadXmlEntities();
                TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                nodeIterator.MoveNext();

                string propsXml = xmlController.SerializeObjectToXML(nodeIterator.Current.Tag);

                if (!System.IO.Directory.Exists(((ProjectProperties)nodeIterator.Current.Tag).ProjectSavedPath))
                {
                    System.IO.Directory.CreateDirectory(((ProjectProperties)nodeIterator.Current.Tag).ProjectSavedPath);
                }

                string path = ((ProjectProperties)nodeIterator.Current.Tag).ProjectSavedPath + @"\\" + ((ProjectProperties)nodeIterator.Current.Tag).Name + ".rstp";

                System.IO.StreamWriter file = new System.IO.StreamWriter(path);
                file.WriteLine(propsXml);
                file.Close();

                this.btnSave.IsEnabled = this.isEdited = false;

                // send notification
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Project saved successfully", ImagePath = "/Images/16x16-Valid.png" });
            }
            catch (Exception ex)
            {
                this.EditedProject();
                throw (ex);
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnSave_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnOpenProperties_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnOpenProperties_Click entered");

                if (this.isEdited)
                {
                    if (MessageBox.Show("You have unsaved changes within the current project, if you continue, all changes will be lost. Do you wish to continue?", "Unsaved Changes", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.No)
                    {
                        Mouse.OverrideCursor = null;
                        return;
                    }
                }

                BrowseProjects openBrowseProject = new BrowseProjects();
                openBrowseProject.OpenedProject += new BrowseProjects.OpenProject(openBrowseProject_OpenedProject);
                openBrowseProject.Owner = this;
                openBrowseProject.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;                
                openBrowseProject.ShowDialog();

            }
            finally
            {                
                this.MainApp.LogMessage("Info","btnOpenProperties_Click exited");
                // Mouse.OverrideCursor = null;
            }
        }
        private void RibbonWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","RibbonWindow_Closing entered");

                if (this.isEdited)
                {
                    if (MessageBox.Show("You have unsaved changes within the current project, if you continue, all changes will be lost. Do you wish to continue?", "Unsaved Changes", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.No) e.Cancel = true;
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","RibbonWindow_Closing exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnSaveParameters_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnSaveParameters_Click entered");

                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                if (selectedNode.Tag is ClassProperties)
                {
                    ParameterValue[] rptParams = this.ctrlLoadReport.GetReportParameters();

                    ((ClassProperties)selectedNode.Tag).ReportParameters = rptParams;

                    TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                    nodeIterator.MoveNext();
                    for (int loop = 0; loop < ((ProjectProperties)nodeIterator.Current.Tag).ClassProperties.Count; loop++)
                    {
                        if (((ProjectProperties)nodeIterator.Current.Tag).ClassProperties[loop].Name == ((ClassProperties)selectedNode.Tag).Name)
                        {
                            ((ProjectProperties)nodeIterator.Current.Tag).ClassProperties[loop].ReportParameters = rptParams;
                            this.btnSaveParameters.IsEnabled = false;
                            break;
                        }
                    }

                    this.UpdateNotifications(this, new NotificationArgs() { Message = "Report parameters saved to class properties - please now save project", ImagePath = "/Images/16x16-Information.png" });
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnSaveParameters_Click exited");
            }
        }
        private void btnCutPasteCode_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnCutPasteCode_Click entered");
                this.ctrlGenerateTestCode.PutCodeIntoClipboard();
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Tests copied to clipboard successfully", ImagePath = "/Images/16x16-Valid.png" });
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnCutPasteCode_Click exited");
            }
        }
        private void btnUserGuide_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnUserGuide_Click entered");

                string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\Data\Help.doc";
                Process wordProcess = new Process();
                wordProcess.StartInfo.FileName = path;
                wordProcess.StartInfo.UseShellExecute = true;
                wordProcess.Start();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnUserGuide_Click exited");
            }
        }
        private void btnAbout_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnAbout_Click entered");

                About aboutWindow = new About(IsRegistered);
                aboutWindow.ValidatedKey += new About.ValidateKey(aboutWindow_ValidatedKey);
                aboutWindow.Owner = this;
                aboutWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
                aboutWindow.ShowDialog();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnAbout_Click exited");
            }
        }        
        private void btnReportValidateServer_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnReportValidateServer_Click entered");

                ValidateWebSerivce validate = new ValidateWebSerivce();
                string errorMessage = string.Empty;
                if (!validate.ServiceExists(this.reportServerUrl.Text, false, out errorMessage))
                {
                    MessageBox.Show(errorMessage);
                    this.lstBoxNotifications.Items.Add(new System.Windows.Controls.ListBoxItem() { Content = errorMessage });
                }
                else
                {                    
                    this.UpdateNotifications(this, new NotificationArgs() { Message = "Report server Url is valid", ImagePath = "/Images/16x16-Valid.png" });
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnReportValidateServer_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnReportValiadetService_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnReportValiadetService_Click entered");

                ValidateWebSerivce validate = new ValidateWebSerivce();
                string errorMessage = string.Empty;
                if (!validate.ServiceExists(this.serviceUrl.Text, false, out errorMessage))
                {
                    MessageBox.Show(errorMessage);
                }
                else
                {
                    this.UpdateNotifications(this, new NotificationArgs() { Message = "Reporting service Url is valid", ImagePath = "/Images/16x16-Valid.png" });
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnReportValiadetService_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnReportCallReport_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","btnReportCallReport_Click entered");

                this.ctrlLoadReport.CallReport();
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Report called", ImagePath = "/Images/16x16-Valid.png" });
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnReportCallReport_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnReportGerParams_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnReportGerParams_Click entered");
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Getting report parameters...", ImagePath = "/Images/16x16-Information.png" });
                this.ctrlLoadReport.GetReportParams();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnReportGerParams_Click exited");
            }
        }
        private void btnClassDelete_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnClassDelete_Click entered");

                // get selected node -> Tag is ClassProperties
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                if (selectedNode.Tag is ClassProperties)
                {
                   
                    // class properties
                    ClassProperties clsProps = (ClassProperties)selectedNode.Tag;

                    if (MessageBox.Show("Are you sure you wish to delete the class - '" + clsProps.Name + "'. Click 'OK' to delete.", "Delete Class", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.Cancel) return;

                    // project properties
                    TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                    nodeIterator.MoveNext();
                    ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;

                    props.ClassProperties.Remove(clsProps); // delete class from project
                    nodeIterator.Current.Tag = props; // reassign to project root
                    //this.projectFilesView.Nodes[0].Nodes.RemoveAt(1); 
                    //this.projectFilesView.Nodes[0].Nodes.Remove(this.projectFilesView.FocusedNode);

                    //TreeListNode[] nodes = { this.projectFilesView.FocusedNode };
                    //nodes[0] = this.projectFilesView.FocusedNode;
                    //this.projectFilesView.Nodes[0].Nodes.CopyTo(nodes, this.projectFilesView.Nodes.Count+1);

                    //int pos = this.projectFilesView.Nodes[0].Nodes.IndexOf(this.projectFilesView.FocusedNode);
                    //this.projectFilesView.Nodes[0].Nodes.RemoveAt(pos);

                    this.projectFilesView.Nodes[0].Nodes.Remove(this.projectFilesView.FocusedNode);

                    //(new System.Collections.Generic.Mscorlib_CollectionDebugView<DevExpress.Xpf.Grid.TreeListNode>(this.projectFilesView.Nodes[0].Nodes)).Items[0]
                    //DevExpress.Xpf.Grid.TreeListNode X = (DevExpress.Xpf.Grid.TreeListNode(this.projectFilesView.Nodes[0].Nodes)).Items[0];
                    //(System.Collections.Generic.Mscorlib_CollectionDebugView<DevExpress.Xpf.Grid.TreeListNode(this.projectFilesView.Nodes[0].Nodes)).Items[0]

                    // this.projectFilesView.Nodes[0].Nodes[1].Nodes.RemoveAt(this.projectFilesView.FocusedNode.RowHandle);
                    // this.projectFilesView.Nodes[0].Nodes.RemoveAt(this.projectFilesView.FocusedNode.RowHandle);
                    this.projectFilesColumns.RefreshData();

                    this.EditedProject();
                    this.btnSave.IsEnabled = true;

                    this.UpdateNotifications(this, new NotificationArgs() { Message = "Class deleted", ImagePath = "/Images/16x16-Valid.png" });
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnClassDelete_Click exited");
            }
        }
        private void btnReportCreateTests_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnReportCreateTests_Click entered");
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Creating tests...", ImagePath = "/Images/16x16-Information.png" });

                this.ctrlBuildAssertions.GenerateCode();
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnReportCreateTests_Click exited");
            }
        }
        private void btnPrintCode_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.MainApp.LogMessage("Info","btnPrintCode_Click entered");

                Mouse.OverrideCursor = Cursors.Wait;
                this.UpdateNotifications(this, new NotificationArgs() { Message = "Printing tests...", ImagePath = "/Images/16x16-Information.png" });
                PrintUsingDocumentCondensed(this.ctrlGenerateTestCode.txtCode.Text);
            }
            finally
            {
                this.MainApp.LogMessage("Info","btnPrintCode_Click exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void btnRemoveClassAssertions_Click(object sender, RoutedEventArgs e)
        {
             TreeListNode selectedNode = this.projectFilesView.FocusedNode;
             if (selectedNode.Tag is ClassProperties)
             {
                 // class properties
                 ClassProperties clsProps = (ClassProperties)selectedNode.Tag;

                 if (MessageBox.Show("Are you sure you wish to delete all the assertions for this class - '" + clsProps.Name + "'. Click 'OK' to delete.", "Delete Class Assertions", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.Cancel) return;

                 foreach (NodeDetails details in clsProps.TreeNodeAssertionDetails)
                 {
                     this.ctrlBuildAssertions.LstNodeDetails.Remove(details);
                 }

                 clsProps.TreeNodeAssertionDetails = new List<NodeDetails>();
                 selectedNode.Tag = clsProps;

                 // TODO: - loop through xml tree and get each leaf's tag and remove assertion(s)
             }
        }
        #endregion

        #region Key Security\Registration
        private bool IsKeyValid(List<string> key)
        {
            try
            {
                bool validKey = false;

                // go through each row individually

                // 1st
                for (int innerLoop = 0; innerLoop <= passwordSt.GetLength(1) - 1; innerLoop++)
                {
                    if (passwordSt[0, innerLoop] == key[0]) // first row
                    {
                        validKey = true;
                        break;
                    }
                }

                if (!validKey) return false;

                // 2nd
                validKey = false;
                for (int innerLoop = 0; innerLoop <= passwordSt.GetLength(1) - 1; innerLoop++)
                {
                    if (passwordSt[1, innerLoop] == key[1]) // first row
                    {
                        validKey = true;
                        break;
                    }
                }

                if (!validKey) return false;

                // 3rd
                validKey = false;
                for (int innerLoop = 0; innerLoop <= passwordSt.GetLength(1) - 1; innerLoop++)
                {
                    if (passwordSt[2, innerLoop] == key[2]) // first row
                    {
                        validKey = true;
                        break;
                    }
                }

                if (!validKey) return false;

                // 4th
                validKey = false;
                for (int innerLoop = 0; innerLoop <= passwordSt.GetLength(1) - 1; innerLoop++)
                {
                    if (passwordSt[3, innerLoop] == key[3]) // first row
                    {
                        validKey = true;
                        break;
                    }
                }

                if (!validKey) return false;

                // 5th
                validKey = false;
                for (int innerLoop = 0; innerLoop <= passwordSt.GetLength(1) - 1; innerLoop++)
                {
                    if (passwordSt[4, innerLoop] == key[4]) // first row
                    {
                        validKey = true;
                        break;
                    }
                }

                if (!validKey) return false;

                return true;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }
        private List<string> RetrieveListFromString(string longKey)
        {
            List<string> lstLongKey = new List<string>();
            string[] aryKey = longKey.Split('-');
            foreach (string keyPart in aryKey)
            {
                lstLongKey.Add(keyPart);
            }
            return lstLongKey;
        }
        private void aboutWindow_ValidatedKey(List<string> key)
        {
            try
            {
                string longKey = string.Empty;
                string longKeyHash = string.Empty;
                bool validKey = this.IsKeyValid(key);

                if (validKey)
                {
                    foreach (string keyPart in key)
                    {
                        longKey += keyPart + "-";
                    }
                    longKey = longKey.Remove(longKey.Length - 1, 1);

                    string encryptedKey = Security.Encrypt(longKey, this.GetMacAddress(), true);

                    // validate key and registery 5 digits
                    Microsoft.Win32.RegistryKey mykey;
                    mykey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(this.RegKey);
                    mykey.SetValue("SystemLive", encryptedKey);
                    mykey.Close();
                    
                    MessageBox.Show("Key has been successfully validated - please restart application for changes to take effect. \n\nThank you for using 'Reporting Services Test Generator.'", "Valid Registration", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                else
                {
                    MessageBox.Show("Key was not successfully validated. Please re-enter.", "Invalid Registration", MessageBoxButton.OK, MessageBoxImage.Information);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("Key was not successfully validated. Please re-enter.", "Invalid Registration", MessageBoxButton.OK, MessageBoxImage.Information);
                throw (ex);
            }
        }
        private bool IsApplicationRegistered()
        {
            // get key
            Microsoft.Win32.RegistryKey regKey;
            regKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(this.RegKey);
            if (regKey == null) return false;

            string encryptedKey = (string)regKey.GetValue("SystemLive");

            if (String.IsNullOrEmpty(encryptedKey)) return false; // nothing was registered

            // verify key in registry
            string decryptedKey = Security.Decrypt(encryptedKey, this.GetMacAddress(), true);
            return this.IsKeyValid(this.RetrieveListFromString(decryptedKey));
        }
        private string GetMacAddress()
        {
                try
                {
                    string MACAddress = String.Empty;
                    ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                    ManagementObjectCollection moc = mc.GetInstances();
                    
                    foreach (ManagementObject mo in moc)
                    {
                        if (MACAddress == String.Empty) // only return MAC Address from first card  
                        {
                            if ((bool)mo["IPEnabled"] == true) MACAddress = mo["MacAddress"].ToString();
                        }
                        mo.Dispose();
                    }

                    MACAddress = MACAddress.Replace(":", "");

                    if (String.IsNullOrEmpty(MACAddress)) MACAddress = "FinnHarpsForEver"; // create dummy Mac Address - always something to encrypt with

                    return MACAddress;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }                                     
        }
        #endregion

        #region Private Methods
        private void DetermineIfApplicationRegistered()
        {
            this.IsRegistered = this.IsApplicationRegistered();
            if (!this.IsRegistered)
            {
                // trial mode 
                this.TrialMode();
                // MessageBox.Show("Application has not been registered and will run in demo mode", "Demo Mode", MessageBoxButton.OK, MessageBoxImage.Information);

                this.statusText.Text = "This application has not been registered, and will run in demo mode.";
            }
            else
            {
                // this.statusItem.Visibility = System.Windows.Visibility.Collapsed;
                this.statusBar.Visibility = System.Windows.Visibility.Collapsed; 
            }
        }
        private void TrialMode()
        {
            this.btnClassDelete.IsEnabled = this.btnClassEditProperties.IsEnabled = this.btnNewClass.IsEnabled = false;
            this.btnSave.Visibility = System.Windows.Visibility.Hidden;
        }
        private void PrintUsingDocumentCondensed(string text, string printCaption = "Asynchronous Ltd. - Reporting Services Generated Tests")
        {
            try
            {
                this.MainApp.LogMessage("Info","PrintUsingDocumentCondensed entered");

                // Create the document, passing a new paragraph and new run using text
                FlowDocument doc = new FlowDocument(new Paragraph(new Run(text)));
                doc.PagePadding = new Thickness(100); //'Creates margin around the page

                System.Windows.Controls.PrintDialog diag = new System.Windows.Controls.PrintDialog(); // 'Used to perform printing
                // Send the document to the printer            
                DocumentPaginator paginator = ((IDocumentPaginatorSource)doc).DocumentPaginator;
                diag.PrintDocument(paginator, printCaption);
            }
            finally
            {
                this.MainApp.LogMessage("Info","PrintUsingDocumentCondensed exited");
            }
        }
        private void openBrowseProject_OpenedProject(object sender, string projectPath)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","openBrowseProject_OpenedProject entered");

                // test back into props object   
                int projectAssertionCounter = 0;
                ReadXmlEntities xmlController = new ReadXmlEntities();
                System.IO.StreamReader file = new System.IO.StreamReader(projectPath);
                string projectXmlContects = file.ReadToEnd();
                file.Close();
                ProjectProperties props = (ProjectProperties)xmlController.DeserializeXMLToObject(projectXmlContects, typeof(ProjectProperties));

                // loop through and get previously created asserts
                List<NodeDetails> details = new List<NodeDetails>();

                foreach (ClassProperties clsProps in props.ClassProperties)
                {
                    if (clsProps.TreeNodeAssertionDetails == null) break;
                    foreach (NodeDetails assert in clsProps.TreeNodeAssertionDetails)
                    {
                        details.Add(assert);
                        projectAssertionCounter += assert.Assertions.Count;
                    }
                }

                this.btnReportCreateTests.IsEnabled = details.Count > 0 ? true : false;
                this.ctrlBuildAssertions.LstNodeDetails = details; // update control with opened project assetions                

                // set properties
                this.NumberOfTests.Text = projectAssertionCounter.ToString();
                this.txtblkCreated.Text = ((ProjectProperties)props).ProjectCraeted.ToString();
                this.txtblkSavedPath.Text = ((ProjectProperties)props).ProjectSavedPath;
                this.serviceUrl.Text = ((ProjectProperties)props).ReportWebServiceUrl;
                this.reportServerUrl.Text = ((ProjectProperties)props).ReportServerUrl;

                // build main project\class tree
                projectFilesView.Nodes.Clear(); // new project
                TreeListNode rootNode = CreateRootNode((ProjectProperties)props);
                foreach (ClassProperties cls in props.ClassProperties) this.CreateChildNode(rootNode, cls);

                // select project or class node
                this.projectFilesView.FocusedNode = projectFilesView.GetNodeByContent(props);

                this.isEdited = false; // new project - all clean               

                // build assertions control
                this.ctrlBuildAssertions.trViewReportXml.Items.Clear();
                this.ctrlBuildAssertions.lstBoxAssertions.Items.Clear();
                this.ctrlGenerateTestCode.txtCode.Clear(); // clear any previous code
                this.ctrlBuildAssertions.buildAsertGrid.IsEnabled = false;
                this.ctrlBuildAssertions.TestFramework = ((ProjectProperties)props).TestFramework;
                this.ctrlBuildAssertions.Language = ((ProjectProperties)props).Language;

                // project properties
                if (((ProjectProperties)props).Language == ClassEnumerations.CodeLanguages.CSharp) this.languageCSharp.IsChecked = true;
                else this.languageVB.IsChecked = true;

                if (((ProjectProperties)props).TestFramework == ClassEnumerations.TestFrameworks.NUnit) this.chkBxNUnitTest.IsChecked = true;
                else this.chkBxVSTest.IsChecked = true;

                // ribbonbar menu
                this.btnReportValiadetService.IsEnabled = true;
                this.btnReportValidateServer.IsEnabled = true;
                this.btnNewClass.IsEnabled = true;
                this.btnEditProperties.IsEnabled = true;
                this.btnCutPasteCode.IsEnabled = this.btnPrintCode.IsEnabled = false;

                this.UpdateNotifications(this, new NotificationArgs() { Message = "Project '" + ((ProjectProperties)props).Name + "' loaded successfully", ImagePath = "/Images/16x16-Valid.png" });
            }
            catch (Exception ex)
            {
                this.btnReportValiadetService.IsEnabled = false;
                this.btnReportValidateServer.IsEnabled = false;
                this.btnReportGerParams.IsEnabled = false;
                this.btnReportCallReport.IsEnabled = false;
                this.btnNewClass.IsEnabled = false;
                this.btnEditProperties.IsEnabled = false;

                this.UpdateNotifications(this, new NotificationArgs() { Message = "Failed to open project - " + ex.Message, ImagePath = "/Images/16x16-Errors.png" });

                throw (ex);
            }
            finally
            {
                this.imgLoadreport.Visibility = System.Windows.Visibility.Collapsed;
                this.DemoDockContainer.Visibility = System.Windows.Visibility.Visible;
                this.ctrlLoadReport.Visibility = System.Windows.Visibility.Visible;

                this.MainApp.LogMessage("Info","openBrowseProject_OpenedProject exited");
                // Mouse.OverrideCursor = null;
            }

        }
        private void newProjectChildWindow_NotifyedUser(object sender, NotificationArgs arg)
        {
            try
            {
                this.MainApp.LogMessage("Info","newProjectChildWindow_NotifyedUser entered");
                this.UpdateNotifications(this, new NotificationArgs() { Message = arg.Message, ImagePath = arg.ImagePath });
            }
            finally
            {
                this.MainApp.LogMessage("Info","newProjectChildWindow_NotifyedUser exited");
            }
        }
        private bool newProjectChildWindow_CheckedDoesClassNameExist(object sender, string className)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","newProjectChildWindow_CheckedDoesClassNameExist entered");

                isNewObject = ClassEnumerations.ApplicationStatus.New;

                // get root node properties
                TreeListNodeIterator nodeIterator = new TreeListNodeIterator(this.projectFilesView.Nodes, true);
                nodeIterator.MoveNext();
                ProjectProperties props = (ProjectProperties)nodeIterator.Current.Tag;

                if (props.ClassProperties == null) return true; // first class in project

                foreach (ClassProperties clsProps in props.ClassProperties)
                {
                    if (String.Compare(clsProps.Name, className, System.StringComparison.CurrentCultureIgnoreCase) == 0)
                    {
                        this.UpdateNotifications(this, new NotificationArgs() { Message = "Class name not unique", ImagePath = "/Images/16x16-Error.png" });
                        return false;
                    }
                }
                return true;
            }
            finally
            {
                this.MainApp.LogMessage("Info","newProjectChildWindow_CheckedDoesClassNameExist exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void UpdateLoadReportControl()
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","UpdateLoadReportControl entered");

                this.ctrlLoadReport.ReportUsername = !String.IsNullOrEmpty(this.credentialsUsername.Text) ? this.credentialsUsername.Text : string.Empty;
                this.ctrlLoadReport.ReportPassword = !String.IsNullOrEmpty(this.credentialsPassword.Text) ? this.credentialsPassword.Text : string.Empty;
                this.ctrlLoadReport.ReportDomian = !String.IsNullOrEmpty(this.credentialsDomain.Text) ? this.credentialsDomain.Text : string.Empty;
                this.ctrlLoadReport.ReportPath = this.txtBlkReportPath.Text;
                this.ctrlLoadReport.ReportServiceUrl = this.serviceUrl.Text;

                this.ctrlLoadReport.ReportName = this.txtBlkReportname.Text;

                // Update parameters (if necessary)
                TreeListNode selectedNode = this.projectFilesView.FocusedNode;
                if (selectedNode.Tag is ClassProperties)
                {
                    this.ctrlLoadReport.UpdateReportParameters(((ClassProperties)selectedNode.Tag).ReportParameters);
                }
            }
            finally
            {
                this.MainApp.LogMessage("Info","UpdateLoadReportControl exited");
                Mouse.OverrideCursor = null;
            }
        }
        private void UpdateBuildAssertionControl(string projectName, ParameterValue[] rptParams)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.MainApp.LogMessage("Info","UpdateBuildAssertionControl entered");

                this.ctrlBuildAssertions.ProjectName = projectName;
                this.ctrlBuildAssertions.ReportName = this.txtBlkReportname.Text;
                this.ctrlBuildAssertions.ReportingServiceUrl = this.serviceUrl.Text;
                this.ctrlBuildAssertions.Parameters = rptParams;
            }
            finally
            {
                this.MainApp.LogMessage("Info","UpdateBuildAssertionControl exited");
                Mouse.OverrideCursor = null;
            }
        }
        #endregion

        #region Public Methods
        public void UpdateNotifications(string message)
        {
            try
            {
                this.MainApp.LogMessage("Info","UpdateNotifications entered");
                this.UpdateNotifications(this, new NotificationArgs() { Message = message, ImagePath = "/Images/16x16-Errors.png" });
            }
            finally
            {
                this.MainApp.LogMessage("Info","UpdateNotifications exited");
            }
        }
        #endregion
    }
}
